package com.talkyun.openx.server.helper;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MatchHelper {
    public static class MatchRule {
        // *.*, User*.login*, UserService.* ...
        private boolean igAll, igMap, igMth;
        private boolean mapLike, mthLike;
        private String cp, mp;

        public MatchRule(String pattern) {
            try {
                if (pattern.equals("*")) {
                    this.igAll = true;
                } else {
                    int pos = pattern.lastIndexOf(".");
                    this.cp = pattern.substring(0, pos);
                    this.mp = pattern.substring(pos + 1);
                    if (cp.equals("*")) {
                        this.igMap = true;
                    } else {
                        this.mapLike = cp.indexOf("*") != -1;
                        this.cp = this.trim(cp);
                    }
                    if (mp.equals("*")) {
                        this.igMth = true;
                    } else {
                        this.mthLike = mp.indexOf("*") != -1;
                        this.mp = this.trim(mp);
                    }
                }
            } catch (Throwable t) {
                throw new RuntimeException("Pattern error! " + pattern, t);
            }
        }

        public boolean isMatched(String mapping, String method) {
            if (igAll) {
                return true;
            }
            // check mapping
            if (!igMap) {
                if (mapLike) {
                    if (!mapping.startsWith(cp)) {
                        return false;
                    }
                } else {
                    if (!mapping.equals(cp)) {
                        return false;
                    }
                }
            }
            // check method
            if (!igMth) {
                if (mthLike) {
                    return method.startsWith(mp);
                } else {
                    return method.equals(mp);
                }
            }
            return true;
        }

        private String trim(String pt) {
            int pos = pt.indexOf("*");
            if (pos != -1) {
                return pt.substring(0, pos);
            } else {
                return pt;
            }
        }
    }

    private static final Map<String, MatchRule> p2r = new ConcurrentHashMap<String, MatchRule>();

    public static boolean isMatched(String pattern, String mapping, String method) {
        MatchRule rule = p2r.get(pattern);
        if (rule == null) {
            rule = new MatchRule(pattern);
            p2r.put(pattern, rule);
        }
        return rule.isMatched(mapping, method);
    }
}
